#ifndef __SWF_PRIMITIVES__
#define __SWF_PRIMITIVES__

#include <stdint.h>
#include <string>
#include <vector>
//#include "../../interface/stream.h"
//#include "../../interface/coptr.h"

namespace swf
{
	typedef long		bool_t;
	typedef uint8_t		_UI8;
	typedef uint16_t	_UI16;
	typedef uint32_t	_UI32;
	typedef uint64_t	_UI64;
	typedef int8_t		_SI8;
	typedef int16_t		_SI16;
	typedef int32_t		_SI32;
	typedef int64_t		_SI64;
	typedef double		_D64;

#define needge(x)		{ swf::bool_t r = (x); if( r < 0 ) return r; }
#define needgz(x)		{ swf::bool_t r = (x); if( r <= 0 ) return r; }
#define neednz(x)		{ swf::bool_t r = (x); if( !r ) return r; }
#define ifnot(x)		if( !(x) ) 

	struct iinstm
	{
		virtual long seek( int64_t l, size_t method ) = 0;
		virtual long read( void * pbuf, size_t cb, size_t * eff ) = 0;
		virtual uint64_t tell() = 0;
	};

	struct BxStream : iinstm
	{
		xm::iptr<xm::IKBStream> file;
		BxStream(xm::IKBStream * afile ) : file(afile)
		{}
		virtual long seek( int64_t l, size_t method )
		{
			return file->Seek( l, (xm::SEEK_FORM)method );
		}
		virtual long read( void * pbuf, size_t cb, size_t * eff )
		{
			return file->Read( pbuf, cb, eff );
		}
		virtual uint64_t tell() 
		{
			UINT64 _t = 0;
			if( 0 > file->Tell( &_t ) ) return 0;
			return _t;
		}
	};

	struct StreamIn
	{
		iinstm *	_sp;
		size_t		_bitv;	// 1~7 
		uint8_t		_word;
		enum { WordBits = sizeof(uint8_t)*8 };
		StreamIn(iinstm* is) : _bitv(0), _word(0), _sp(is)
		{}
		size_t tell()
		{
			return (size_t)_sp->tell();
		}
		iinstm* input()
		{
			return _sp;
		}
		bool_t skip( long l )
		{
			long lr = _sp->seek( l, SEEK_CUR );
			return lr >= 0;
		}
		uint8_t get_hbits( size_t bits )
		{
			uint8_t mask = -1;
			mask <<= (WordBits-_bitv);
			uint8_t ret = (( _word & mask ) >> (WordBits-bits));
			_word <<= bits;
			_bitv -= bits;
			return ret;
		}
		bool_t load_word( )
		{
			size_t eff = 0;
			long lr = _sp->read( &_word, sizeof(_word), &eff );
			if( lr < 0 || eff != sizeof(_word) ) return false;
			_bitv = eff*8;
			return true;
		}
		template < class T >
		bool_t readubits( size_t bits, T& t )
		{
			t = 0;
			size_t _read = 0;
			while( bits )
			{
				if( !_bitv ) neednz( load_word() );
				_read = _bitv < bits ? _bitv : bits;
				t <<= _read;
				t |= get_hbits(_read);
				bits -= _read;
			}
			return true;
		}
		template < class T >
		bool_t readsbits( size_t bits, T& t )
		{
			size_t signbit = bits-1;
			t = 0;
			size_t _read = 0;
			while( bits )
			{
				if( !_bitv ) neednz( load_word() );
				_read = _bitv < bits ? _bitv : bits;
				t <<= _read;
				t |= get_hbits(_read);
				bits -= _read;
			}
			if( t & (1<<signbit) )	t |= ((-1)<<(signbit+1));
			return true;
		}
		template < class T >
		bool_t read( T& t )
		{
			_bitv = 0;
			size_t eff = 0;
			long lr = _sp->read( &t, sizeof(t), &eff );
			if( lr < 0 || eff != sizeof(t) ) return false;
			return true;
		}
		bool_t read( void * p, size_t cb )
		{
			_bitv = 0;
			size_t eff = 0;
			long lr = _sp->read( p, cb, &eff );
			if( lr < 0 || eff != cb ) return false;
			return true;
		}
	};

	struct STRING
	{
		std::string s;
		bool_t read( StreamIn & is )
		{
			char tmp = 0;
			while( is.read( tmp ) )
			{
				if( !tmp ) return true;
				s.push_back( tmp );
			}
			return false;
		}
	};

	struct RECT
	{
		int32_t	left;
		int32_t	right;
		int32_t	top;
		int32_t	bottom;
		bool_t read( StreamIn & is )
		{
			uint8_t nbits;
			neednz( is.readubits( 5, nbits ) );
			neednz( is.readsbits( nbits, left ) );
			neednz( is.readsbits( nbits, right ) );
			neednz( is.readsbits( nbits, top ) );
			neednz( is.readsbits( nbits, bottom ) );
			return true;
		}
	};

	template < size_t bits >
	struct NB8
	{
		uint8_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readubits( bits, i ) );
		}
	};
	template < size_t bits >
	struct NB16
	{
		uint16_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readubits( bits, i ) );
		}
	};
	template < size_t bits >
	struct NB32
	{
		uint32_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readubits( bits, i ) );
		}
	};
	template < size_t bits >
	struct NB64
	{
		uint64_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readubits( bits, i ) );
		}
	};

	template < size_t bits >
	struct SB8
	{
		int8_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readsbits( bits, i ) );
		}
	};
	template < size_t bits >
	struct SB16
	{
		int16_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readsbits( bits, i ) );
		}
	};
	template < size_t bits >
	struct SB32
	{
		int32_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readsbits( bits, i ) );
		}
	};
	template < size_t bits >
	struct SB64
	{
		int64_t i;
		bool_t read( StreamIn & is )
		{
			return( is.readsbits( bits, i ) );
		}
	};

	struct UI8
	{
		uint8_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 8, i );
		}
	};
	struct UI16
	{
		uint16_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 16, i );
		}
	};
	struct UI32
	{
		uint32_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 32, i );
		}
	};
	struct UI64
	{
		uint64_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 64, i );
		}
	};
	struct SI8
	{
		int8_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 8, i );
		}
	};
	struct SI16
	{
		int16_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 16, i );
		}
	};
	struct SI32
	{
		int32_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 32, i );
		}
	};
	struct SI64
	{
		int64_t	i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 64, i );
		}
	};
	struct EU32
	{
		uint32_t i;
		bool_t read( StreamIn & is )
		{
			return is.readubits( 32, i );
		}
		int GetEncodedU32(unsigned char*& pos)
		{
			int result = pos[0];
			if (!(result & 0x00000080))
			{
				pos++;
				return result;
			}
			result = (result & 0x0000007f) | pos[1]<<7;
			if (!(result & 0x00004000))
			{
				pos += 2;
				return result;
			}
			result = (result & 0x00003fff) | pos[2]<<14;
			if (!(result & 0x00200000))
			{
				pos += 3;
				return result;
			}
			result = (result & 0x001fffff) | pos[3]<<21;
			if (!(result & 0x10000000))
			{
				pos += 4;
				return result;
			}
			result = (result & 0x0fffffff) | pos[4]<<28;
			pos += 5;
			return result;
		}
	};

	namespace abc
	{
		typedef _UI8	u8;
		typedef _UI16	u16;
		struct u32
		{
			_UI32 i;
			u32():i(0){};
			bool_t read( StreamIn & is )
			{
				_UI8 b;
				
				neednz( is.read(b) );
				i = b;
				ifnot( i & 0x80 ) return true;

				neednz( is.read(b) );
				(i &= 0x7f ) |= ((uint32_t)b << 7);
				ifnot( i & 0x4000 ) return true;

				neednz( is.read(b) );
				(i &= 0x3fff ) |= ((uint32_t)b << 14);
				ifnot( i & 0x200000 ) return true;

				neednz( is.read(b) );
				(i &= 0x1fffff ) |= ((uint32_t)b << 21);
				ifnot( i & 0x10000000 ) return true;

				neednz( is.read(b) );
				(i &= 0x0fffffff ) |= ((uint32_t)b << 28);

				return true;
			}
		};
		struct u30
		{
			_UI32 i;
			u30():i(0){};
			bool_t read( StreamIn & is )
			{
				u32 _u32;
				neednz( _u32.read(is) );
				i = _u32.i & (-1>>2);
				return true;
			}
		};
		struct s32
		{
			_SI32 i;
			s32():i(0){};
			bool_t read( StreamIn & is )
			{
				size_t b = read_(is);
				if( !b ) return false;
				if( i & (1<<b) ) i |= (-1<<(b+1));
				return true;
			}
		private:
			size_t read_( StreamIn & is )
			{
				_UI8 b;

				neednz( is.read(b) );
				i = b;
				ifnot( i & 0x80 ) return 6;

				neednz( is.read(b) );
				(i &= 0x7f ) |= ((uint32_t)b << 7);
				ifnot( i & 0x4000 ) return 13;

				neednz( is.read(b) );
				(i &= 0x3fff ) |= ((uint32_t)b << 14);
				ifnot( i & 0x200000 ) return 20;

				neednz( is.read(b) );
				(i &= 0x1fffff ) |= ((uint32_t)b << 21);
				ifnot( i & 0x10000000 ) return 27;

				neednz( is.read(b) );
				(i &= 0x0fffffff ) |= ((uint32_t)b << 28);

				return 31;
			}
		};
		//struct u16
		//{
		//	_I16 i;
		//	bool_t read( StreamIn & is )
		//	{
		//		return ( is.read( i ) );
		//	}
		//};
		struct s24
		{
			_SI32 i;
			s24():i(0){};
			bool_t read( StreamIn & is )
			{
				_UI8 b[3];
				neednz( is.read( b ) );
				i  = b[2]; i <<= 8;
				i |= b[1]; i <<= 8;
				i |= b[0];
				if( i & (1<<23) ) i |= (-1<<24);
				return true;
			}
		};
		struct d64
		{
			_D64 i;
			d64():i(0){};
			bool_t read( StreamIn & is )
			{
				return( is.read( i ) );
			}
		};

		template < class T >
		struct box
		{
			std::vector<T> items;
			bool_t read( StreamIn & is, size_t c, size_t from = 0 )
			{
				items.resize( c );
				for( size_t i = from; i < c; ++ i )
				{
					neednz( items[i].read(is) );
				}
				return true;
			}
		};
		
		template < class SIZE, class T >
		struct combox : box<T>
		{
			SIZE count;
			bool_t read( StreamIn & is, size_t from = 0 )
			{
				neednz( count.read(is) );
				return box<T>::read( is ,count.i, from );
			}
		};

	};



	



};

#endif